/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package DigestControllers;

import DigestModels.Database;
import DigestViews.MainView;
import DigestViews.AddFood;
import DigestViews.DailySummaryView;
import DigestViews.LoginView;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyAdapter;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.DocumentFilter.FilterBypass;

/**
 * This class controls the functions of the main view.
 *
 * @author Prophet,Tony Sheamus
 */
public class MainViewController {

    ActionListener actionListener;
    MouseListener mouseListener;
    KeyListener keyListener;
    KeyAdapter keyAdapter;
    MainView mainView;
    Database database;
    DefaultTableModel transactionTable;
    AddFoodController addController;
    AddFood addFood;
    String user;

    /**
     * This is the default constructor.
     *
     * @param mainView represents the main to be view.
     * @param database represents the database to be used.
     * @param lg represents the login view used.
     */
    public MainViewController(MainView mainView, Database database, LoginView lg) {
        this.mainView = mainView;
        this.database = database;
        this.database.initComponents();
        this.user = lg.getUsername().getText();
    }

    /**
     * This method initializes the main view components
     */
    public void control() {
        final JTextField search = (JTextField) mainView.getSearchField().getEditor().getEditorComponent();
        keyAdapter = new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                if (e.getSource() == search) {
                    search(search);
                }
            }
        };
        mouseListener = new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent mouseEvent) {
                JList list = null;
                JTable table = null;
                if (mouseEvent.getSource() == mainView.getMainMealList()) {
                    list = (JList) mouseEvent.getSource();
                } else if (mouseEvent.getSource() == mainView.getAccompList()) {
                    list = (JList) mouseEvent.getSource();
                } else if (mouseEvent.getSource() == mainView.getSnackList()) {
                    list = (JList) mouseEvent.getSource();
                } else if (mouseEvent.getSource() == mainView.getDrinkList()) {
                    list = (JList) mouseEvent.getSource();
                } else if (mouseEvent.getSource() == mainView.getSummaryTable()) {
                    table = (JTable) mouseEvent.getSource();
                } else if (mouseEvent.getSource() == mainView.getAddFoodBtn()) {
                    addFood();
                }
                if (list != null) {
                    String item = (String) list.getSelectedValue();
                    //System.out.println(item);
                    addToSummary(item);
                } else if (table != null) {
                    decrementTable(table.getSelectedRow());
                }
            }
        };
        
           
        actionListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == mainView.getCancelBtn()) {
                    clearSummaryTable();
                } else if (e.getSource() == mainView.getExecuteBtn()) {
                    makeOrder();
                } else if (e.getSource() == mainView.getDailyReport()) {
                    dailySummary();
                } else if (e.getSource() == mainView.getExportBtn()) {
                    database.export();
                }
            }
        };
        
        keyListener = new KeyListener() {

            @Override
            public void keyTyped(KeyEvent e) {}

            @Override
            public void keyPressed(KeyEvent e) {
                if(e.getKeyCode() == KeyEvent.VK_ENTER)
                    calculateChange();
            }

            @Override
            public void keyReleased(KeyEvent e) {}
        };
        
        search.addKeyListener(keyAdapter);
        mainView.getMainMealList().addMouseListener(mouseListener);
        mainView.getAccompList().addMouseListener(mouseListener);
        mainView.getSnackList().addMouseListener(mouseListener);
        mainView.getDrinkList().addMouseListener(mouseListener);
        mainView.getAddFoodBtn().addMouseListener(mouseListener);
        transactionTable = new DefaultTableModel(){

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        
        };
        restrictInputToNumbers();
        transactionTable.addColumn("Item Name");
        transactionTable.addColumn("Price");
        transactionTable.addColumn("Quantity");
        mainView.getSummaryTable().setModel(transactionTable);
        mainView.getSummaryTable().addMouseListener(mouseListener);
        mainView.getCancelBtn().addActionListener(actionListener);
        mainView.getExecuteBtn().addActionListener(actionListener);
        mainView.getDailyReport().addActionListener(actionListener);
        mainView.getPaidField().addKeyListener(keyListener);
        loadLists();
    }
    
    /**
     * A method to perform search
     * 
     * @param search
     */
    public void search(final JTextField search) {

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                String request = search.getText();
                if (request.length() < 1) {
                    mainView.getSearchField().hidePopup();
                    updateTable();
                    return;
                }
                ArrayList search = database.suggestSearch(request);
                ArrayList suggestions = (ArrayList) search.get(0);
                Vector columns = (Vector) search.get(1);

                Vector v1 = new Vector();
                /*Vector v2 = (Vector)search.get(1).get(1);
                 Vector v3 = (Vector)search.get(1).get(2);
                 Vector v4 = (Vector)search.get(1).get(3);
                
                
                      //v1.setColumnCount(0); */
                v1.add("amount_paid");
                v1.add("date");
                v1.add("time");
                v1.add("cost");
                      
                
                transactionTable = new DefaultTableModel(columns,v1);
                mainView.getSummaryTable().setModel(transactionTable);
                if (suggestions.size() > 0) {
                    mainView.getSearchField().setModel(new DefaultComboBoxModel(suggestions.toArray()));
                    mainView.getSearchField().setSelectedItem(request);
                    mainView.getSearchField().showPopup();
                } else {
                    mainView.getSearchField().hidePopup();
                }

            }
        });

    }
    
    /**
     * A method to update the table
     */
    public void updateTable() {
        JTable mainTable = mainView.getSummaryTable();
        //mainTable.setEnabled(false);
        Vector<Object> v = new Vector<Object>();
        v.add("name");
        v.add("amount_paid");
        v.add("date");
        v.add("time");
        v.add("cost");
        transactionTable = new DefaultTableModel(database.getTransactionInfo(), v);
        mainTable.setModel(transactionTable);
    }

    /**
     * Upon clicking an item to be ordered this method adds it to the summary
     * table in the main view.
     *
     * @param item represents the item chosen.
     */
    public void addToSummary(String item) {
        for (int i = 0; i < transactionTable.getRowCount(); i++) {
            String s = (String) transactionTable.getValueAt(i, 0);
            if (s.equals(item)) {
                int num = (Integer) transactionTable.getValueAt(i, 2) + 1;
                transactionTable.setValueAt(num, i, 2);
                updateTotal();
                return;
            }
        }
        transactionTable.addRow(database.getItem(item).toArray());
        updateTotal();
    }

    /**
     * This method populates the lists in the main view.
     */
    public void loadLists() {
        mainView.getMainMealList().setListData(database.getItemList("main_meal").toArray());
        mainView.getAccompList().setListData(database.getItemList("accompaniment").toArray());
        mainView.getSnackList().setListData(database.getItemList("snack").toArray());
        mainView.getDrinkList().setListData(database.getItemList("drink").toArray());
//        System.out.println("I was here");
    }

    /**
     * This method updates the total when items are added or removed from the
     * summary.
     */
    public void updateTotal() {
        double sum = 0;
        for (int i = 0; i < transactionTable.getRowCount(); i++) {
            double price = (Double) transactionTable.getValueAt(i, 1);
            int quantity = (Integer) transactionTable.getValueAt(i, 2);
            double product = price * quantity;
            sum = sum + product;
        }
        mainView.getTotalField().setText(sum + "");
    }

    /**
     * This method reduces the quantity of an item on a given row when clicked.
     *
     * @param i represents the index of the row in the table.
     */
    public void decrementTable(int i) {
        int num = (Integer) transactionTable.getValueAt(i, 2) - 1;
        if (num <= 0) {
            transactionTable.removeRow(i);
            updateTotal();
            return;
        }
        transactionTable.setValueAt(num, i, 2);
        updateTotal();
    }

    /*
     * A method that adds food 
     * @param d database
     */
    public void addFood() {
        addFood = new AddFood();
        addController = new AddFoodController(database, addFood);
        addController.control();
    }

    /**
     * This method clears the summary table in the main view.
     */
    public void clearSummaryTable() {
//        for(int i = 0; i< transactionTable.getRowCount();i++){
//            transactionTable.removeRow(i);}
        transactionTable.setRowCount(0);
        mainView.getTotalField().setText("0.0");
        mainView.getPaidField().setEditable(false);
        mainView.getPaidField().setText("0.0");
        mainView.getPaidField().setEditable(true);
        mainView.getChangeField().setText("0.0");
    }

    /**
     * This method calculates change for items ordered in the table.
     */
    public void calculateChange() {
        double total = Double.parseDouble(mainView.getTotalField().getText());
        double amountPaid;
        if (!mainView.getPaidField().getText().isEmpty()) {
            amountPaid = Double.parseDouble(mainView.getPaidField().getText());
        } else {
            amountPaid = 0.0;
        }

        double change = amountPaid - total;
        mainView.getChangeField().setText(change + "");
    }

    /**
     * This method places the order made.
     */
    public void makeOrder() {
        int user_id = database.getCurrWorkerId(user);
        double total = Double.parseDouble(mainView.getTotalField().getText());
        double amountPaid;
        if (!mainView.getPaidField().getText().isEmpty()) {
            amountPaid = Double.parseDouble(mainView.getPaidField().getText());
        } else {
            amountPaid = 0.0;
        }
        double change = amountPaid - total;
        if (change < 0) {
            JOptionPane.showMessageDialog(mainView, "Could not place order. The order is not fully paid for.");
            return;
        }
        mainView.getChangeField().setText(change + "");
        database.addPurchases(transactionTable, total, amountPaid, change, user_id);
        JOptionPane.showMessageDialog(mainView, "Meal Has Been Fully Paid For");
        clearSummaryTable();
    }

    /**
     * This method disallows user from entering anything but numbers in the
     * amount paid text field.
     */
    public void restrictInputToNumbers() {
        ((AbstractDocument) mainView.getPaidField().getDocument()).setDocumentFilter(new DocumentFilter() {
            Pattern regEx = Pattern.compile("\\d*");

            @Override
            public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
                Matcher matcher = regEx.matcher(text);
                if (!matcher.matches()) {
                    return;
                }
                super.replace(fb, offset, length, text, attrs);
            }
        });
    }

    /**
     * This method takes user to the view that shows the daily summary.
     */
    public void dailySummary() {
        DailySummaryView dsv = new DailySummaryView();
        DailySummaryController dsc = new DailySummaryController(dsv, database);
        dsc.control();
    }
}
